#include "ggear_imagebuilderbmp.h"

namespace ggear
{
	namespace gfx
	{
		ImageBuilderBMP::ImageBuilderBMP()
		{}

		ImageBuilderBMP::~ImageBuilderBMP()
		{}

		Image* ImageBuilderBMP::Load(io::Stream& _inStream) const
		{

			BMPHeader bmpHeader;
			_inStream.Read(sizeof(BMPHeader),(u8*) &bmpHeader);

			if(bmpHeader.Key != 0x4D42)
				return null;

			Image* img = new Image(bmpHeader.Width, bmpHeader.Height, Image::PixelFormat_R8G8B8A8);
			
			if(isnull(img)) return null;

			u8* imgData = img->Lock();
			
			if(isnull(imgData))
			{
				delete img;
				return null;
			}

			u8 bytesPerPix = bmpHeader.ColorBits / 8;
			u32 bytesPerRow = bmpHeader.DataSize / bmpHeader.Height;
	
			if(!bytesPerRow)
			{
				bytesPerRow = (bmpHeader.Width * bytesPerPix) + (bmpHeader.Width % 4);
				bmpHeader.DataSize = bytesPerRow  *  bmpHeader.Height;
			}

			_inStream.Seek(bmpHeader.OffBits, true);

			for(u32 i = 0; i < bmpHeader.Height; i++)
			{
				for(u32 j = 0; j < bmpHeader.Width; j++)
				{
					u32 pix = 0xFFFFFFFF;
					_inStream.Read(3,(u8*)&pix);
					drefs(imgData) = (pix >> 16) & 0xFF;
					drefs(imgData + 1) = (pix >> 8) & 0xFF;
					drefs(imgData + 2) = (pix) & 0xFF;
					drefs(imgData + 3) = (pix >> 24);
					imgData += 4;
				}
			}

			return img;
		}

		b8 ImageBuilderBMP::Save(const Image& _img, io::Stream& _outStream) const
		{
			if(isnull(_img.Data())) 
				return false;

			BMPHeader bmpHeader;
			bmpHeader.Key = 0x4D42;
			bmpHeader.Width = _img.Width();
			bmpHeader.Height = _img.Height();
			bmpHeader.Reserved = 0;

			u8* imgData;
			
			_outStream.Write(sizeof(BMPHeader), (u8*) &bmpHeader);
			_outStream.Write(bmpHeader.DataSize, imgData);
			return true;
		}
	}
}